package com.saxtest;

import java.io.InputStream;
import java.util.Vector;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class PraseXML extends DefaultHandler {
	private Vector<String> tagName;
	private Vector<String> tagValue;
	private int step;

	// 开始解析XML文件
	public void startDocument() throws SAXException {
		tagName = new Vector<String>();
		tagValue = new Vector<String>();
		step = 0;
	}

	// 结束解析XML文件
	public void endDocument() throws SAXException {
		for (int i = 0; i < tagName.size(); i++) {
			if (!tagName.get(i).equals("") || tagName.get(i) != null) {
				System.out.print("节点名称：" + tagName.get(i) + "  ");
				System.out.println("节点值：" + tagValue.get(i));
			}
		}
	}

	/**
	 * SAX 解析器采用了基于事件的模型，它在解析 XML 文档的时候可以触发一系列的事件，
	 * 当发现给定的tag的时候，它可以激活一个回调方法，告诉该方法制定的标签已经找到。
	 * SAX 对内存的要求通常会比较低，因为它让开发人员自己来决定所要处理的tag。
	 * 特别是当开发人员只需要处理文档中所包含的部分数据时，SAX 这种扩展能力得到了更好的体现。
	 * 
	 * 在解释到一个开始元素时会调用此方法.但是当元素有重复时可以自己写算法来区分 这些重复的元素.qName是什么? 
	 * <name:page ll=""></name:page>这样写就会抛出SAXException错误 通常情况下qName等于localName
	 */
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		tagName.add(qName);// 节点名称
		// 循环输出属性
		for (int i = 0; i < attributes.getLength(); i++) {
			System.out.print("属性名称：" + attributes.getQName(i) + "   ");	// 获取属性名称
			System.out.println("属性值：" + attributes.getValue(attributes.getQName(i)));// 获取属性值
		}
	}

	/**
	 * 在遇到结束标签时调用此方法
	 */
	public void endElement(String uri, String localName, String qName) throws SAXException {

		step = step + 1;
	}

	/**
	 * 读取标签里的值,ch用来存放某行的xml的字符数据,包括标签,初始大小是2048, 每解释到新的字符会把它添加到char[]里。
	 * 注意,这个char字符会自己管理存储的字符, 并不是每一行就会刷新一次char,start,length是由xml的元素数据确定的, 暂时找不到规律,以后看源代码.
	 * 
	 * 这里一个正标签，反标签都会被执行一次characters，所以在反标签时不用获得其中的值
	 */
	public void characters(char ch[], int start, int length) throws SAXException {
		// 只要当前的标签组的长度一至，值就不赋，则反标签不被计划在内
		if (tagName.size() - 1 == tagValue.size()) {
			tagValue.add(new String(ch, start, length));
		}
	}

	public static void main(String[] args) {
		InputStream filename = PraseXML.class.getClassLoader().getResourceAsStream("test.xml");
		SAXParserFactory spf = SAXParserFactory.newInstance();
		try {
			SAXParser saxParser = spf.newSAXParser();
			saxParser.parse(filename, new PraseXML());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public Vector getTagName() {
		return tagName;
	}

	public void setTagName(Vector tagName) {
		this.tagName = tagName;
	}

	public Vector getTagValue() {
		return tagValue;
	}

	public void setTagValue(Vector tagValue) {
		this.tagValue = tagValue;
	}

}